## Windows (TM) Desktop Wallpaper Install.
# Copyright 2008 Clint Banis.  All rights reserved.
#
# Built on a Windows XP machine.

try:
    class Windows:
        # According to http://support.microsoft.com/default.aspx?scid=97142
        SPI_SETDESKWALLPAPER = 20

        import ctypes

        # Registry settings.
        StretchWallpaperStyle = '2'
        CenterWallpaperStyle = '0'
        TileWallpaperOff = '0'

        DefaultWallpaperStyle = StretchWallpaperStyle

        DesktopKey = 'HKCU\\Control Panel\\Desktop\\'

        @classmethod
        def installWallpaper(self, path):
                self.installRegistry(path)
                self.signalDesktop(path)

        @classmethod
        def signalDesktop(self, path):
            'Signal the Windows Desktop to change the Background Wallpaper.'
            # Active State article #435877.
            #
            # Registers a change event with the windows desktop subsystem causing it
            # to reload the background wallpaper image from the path being set.
            #
            # This should be done after all wallpaper registry changes are made.
            #

            self.ctypes.windll.user32.SystemParametersInfoA \
                    (self.SPI_SETDESKWALLPAPER, 0, path, 0)

        @classmethod
        def installRegistry(self, path):
            a = self.RegistryAPI
            d = self.DesktopKey

            a[d + 'Wallpaper'         ] = path
            a[d + 'OriginalWallpaper' ] = path
            a[d + 'ConvertedWallpaper'] = path

            a[d + 'WallpaperStyle'    ] = self.DefaultWallpaperStyle
            a[d + 'TileWallpaper'     ] = self.TileWallpaperOff

        class RegistryAPI:
            # Concise winreg providing key-value get-set item descriptors.
            import _winreg

            allPermissions = (_winreg.KEY_ALL_ACCESS|
                              _winreg.KEY_CREATE_LINK|
                              _winreg.KEY_CREATE_SUB_KEY|
                              _winreg.KEY_ENUMERATE_SUB_KEYS|
                              _winreg.KEY_EXECUTE|
                              _winreg.KEY_NOTIFY|
                              _winreg.KEY_QUERY_VALUE|
                              _winreg.KEY_READ|
                              _winreg.KEY_SET_VALUE|
                              _winreg.KEY_WRITE)

            keyOpenFlags = (_winreg.KEY_SET_VALUE|_winreg.KEY_QUERY_VALUE)

            # Lookup.
            key_path_aliases = {'HKCU': 'HKEY_CURRENT_USER'}

            def get_key_path(self, path):
                assert type(path) is str
                path = path.replace('/', '\\')
                first = path.find('\\')
                if first >= 0:
                    key = path[:first]
                    path = path[first+1:]

                    # Resolve key.
                    key = self.key_path_aliases.get(key, key)

                    assert key.startswith('HKEY_')
                    return (getattr(self._winreg, key), path)

                return (None, path)

            def get_key_path_name(self, path):
                key, path = self.get_key_path(path)
                last = path.rfind('\\')
                if last >= 0:
                    return (key, path[:last], path[last+1:])

                return (key, path)

            # Registry access.
            def open_key_name(self, path):
                key, path, name = self.get_key_path_name(path)
                return (self._winreg.OpenKey(key, path, 0, self.keyOpenFlags), name)

            def close_with_key_access(self, key, function, *args, **kwd):
                try: return function(key, *args, **kwd)
                finally:
                    self._winreg.CloseKey(key)

            # Accessors.
            def getwith_key_value(self, key, name):
                (data, kind) = self._winreg.QueryValueEx(key, name)
                # assert kind == self._winreg.REG_SZ
                return str(data)

            def setwith_key_value(self, key, name, value):
                return self._winreg.SetValueEx(key, name, 0, self._winreg.REG_SZ, value)

            def get_key_value(self, name):
                key, name = self.open_key_name(name)
                return self.close_with_key_access(key, self.getwith_key_value, name)

            def set_key_value(self, name, value):
                key, name = self.open_key_name(name)
                return self.close_with_key_access(key, self.setwith_key_value, name, value)

            __getitem__ = get_key_value
            __setitem__ = set_key_value

        RegistryAPI = RegistryAPI()

    @classmethod
    def makeShortcut(self, shortcut_path, target_path, *args, **kwd):
        import win32com.client

        shell = win32com.client.Dispatch("WScript.Shell")

        if len(shortcut_path) > 4 and shortcut_path[-4:].lower() != '.lnk':
            shortcut_path = shortcut_path + '.lnk'

        shortcut = shell.CreateShortCut(shortcut_path)
        shortcut.Targetpath = target_path
        # Put arguments in the .Arguments property.
        # What about run-in?
        shortcut.save()

        return shortcut

    # http://www.blog.pythonlibrary.org/?p=21
    ##    # link.py
    ##    # From a demo by Mark Hammond, corrupted by Mike Fletcher
    ##    from win32com.shell import shell
    ##    import pythoncom, os
    ##
    ##    class PyShortcut:
    ##            def __init__( self ):
    ##                    self._base = pythoncom.CoCreateInstance(
    ##                            shell.CLSID_ShellLink, None,
    ##                            pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink
    ##                    )
    ##            def load( self, filename ):
    ##                    # Get an IPersist interface
    ##                    # which allows save/restore of object to/from files
    ##                    self._base.QueryInterface( pythoncom.IID_IPersistFile ).Load( filename )
    ##            def save( self, filename ):
    ##                    self._base.QueryInterface( pythoncom.IID_IPersistFile ).Save( filename,
    ##    0 )
    ##            def __getattr__( self, name ):
    ##                    if name != "_base":
    ##                            return getattr( self._base, name )
    ##
    ##    if __name__=='__main__':
    ##            import sys
    ##            file = sys.argv[1]
    ##            shortcut = PyShortcut()
    ##            if os.path.exists( file ):
    ##                    # load and dump info from file...
    ##                    shortcut.load( file )
    ##                    # now print data...
    ##                    print 'Shortcut in file %s to
    ##    file:\n\t%s\nArguments:\n\t%s\nDescription:\n\t%s\nWorking
    ##    Directory:\n\t%s'%(
    ##                            file,
    ##                            shortcut.GetPath(shell.SLGP_SHORTPATH)[0],
    ##                            shortcut.GetArguments(),
    ##                            shortcut.GetDescription(),
    ##                            shortcut.GetWorkingDirectory()
    ##                    )
    ##            else:
    ##                    # create the shortcut using rest of args...
    ##                    data = map( None, sys.argv[2:], ("SetPath", "SetArguments",
    ##    "SetDescription", "SetWorkingDirectory") )
    ##                    for value, function in data:
    ##                            if value and function:
    ##                                    # call function on each non-null value
    ##                                    getattr( shortcut, function)( value )
    ##                    shortcut.save( file )

    ##    import win32com.client
    ##    import winshell
    ##     
    ##    userDesktop = winshell.desktop()
    ##    shell = win32com.client.Dispatch('WScript.Shell')
    ##     
    ##    shortcut = shell.CreateShortCut(userDesktop + '\\Zimbra Webmail.lnk')
    ##    shortcut.Targetpath = r'C:\Program Files\Mozilla Firefox\firefox.exe'
    ##    shortcut.Arguments = 'http://mysite.com/auth/preauth.php'
    ##    shortcut.WorkingDirectory = r'C:\Program Files\Mozilla Firefox'
    ##    shortcut.save()

    ##    import _winreg
    ##    ffkey = _winreg.OpenKey( _winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mozilla\\Mozilla Firefox')
    ##    ffver = _winreg.QueryValueEx( ffkey, 'CurrentVersion' )[0]
    ##    print ffver
    ##    ffmainkey = _winreg.OpenKey( ffkey, sub + "\\Main" )
    ##    ffpath = _winreg.QueryValueEx( ffmainkey, 'PathToExe' )[0]
    ##    _winreg.CloseKey( ffkey )
    ##    _winreg.CloseKey( ffmainkey )

    ##    import _winreg
    ##    print _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT,
    ##        'FirefoxURL\shell\open\command')

    ##    import win32com.client
    ##    import winshell
    ##     
    ##    shortcut = shell.CreateShortCut(userDesktop + '\\MyShortcut.lnk')
    ##    shortcut.TargetPath = r'Program Files\Mozilla Firefox\firefox.exe'
    ##    shortcut.Arguments = r'http://mysite.com/auth/preauth.php'
    ##    shortcut.WorkingDirectory = r'C:\Program Files\Mozilla Firefox'
    ##    shortcut.save()

    ##    import os
    ##    import winshell
    ##     
    ##    winshell.CreateShortcut (
    ##    Path=os.path.join (winshell.desktop (), "Zimbra Monkeys.lnk"),
    ##    Target=r"c:\Program Files\Mozilla Firefox\firefox.exe",
    ##    Arguments="http://mysite.com/auth/preauth.php",
    ##    Description="Open http://localhost with Firefox",
    ##    StartIn=r'C:\Program Files\Mozilla Firefox'
    ##    )

    # Scheduled Tasks.
    ##    import pythoncom, win32api
    ##    import time
    ##    from win32com.taskscheduler import taskscheduler
    ##
    ##    def create_daily_task(name, cmd, hour=None, minute=None):
    ##        """creates a daily task"""
    ##        cmd = cmd.split()
    ##        ts = pythoncom.CoCreateInstance(taskscheduler.CLSID_CTaskScheduler,None,
    ##                                        pythoncom.CLSCTX_INPROC_SERVER,
    ##                                        taskscheduler.IID_ITaskScheduler)
    ##
    ##        if '%s.job' % name not in ts.Enum():
    ##            task = ts.NewWorkItem(name)
    ##
    ##            task.SetApplicationName(cmd[0])
    ##            task.SetParameters(' '.join(cmd[1:]))
    ##            task.SetPriority(taskscheduler.REALTIME_PRIORITY_CLASS)
    ##            task.SetFlags(taskscheduler.TASK_FLAG_RUN_ONLY_IF_LOGGED_ON)
    ##            task.SetAccountInformation('', None)
    ##            ts.AddWorkItem(name, task)
    ##            run_time = time.localtime(time.time() + 300)
    ##            tr_ind, tr = task.CreateTrigger()
    ##            tt = tr.GetTrigger()
    ##            tt.Flags = 0
    ##            tt.BeginYear = int(time.strftime('%Y', run_time))
    ##            tt.BeginMonth = int(time.strftime('%m', run_time))
    ##            tt.BeginDay = int(time.strftime('%d', run_time))
    ##            if minute is None:
    ##                tt.StartMinute = int(time.strftime('%M', run_time))
    ##            else:
    ##                tt.StartMinute = minute
    ##            if hour is None:
    ##                tt.StartHour = int(time.strftime('%H', run_time))
    ##            else:
    ##                tt.StartHour = hour
    ##            tt.TriggerType = int(taskscheduler.TASK_TIME_TRIGGER_DAILY)
    ##            tr.SetTrigger(tt)
    ##            pf = task.QueryInterface(pythoncom.IID_IPersistFile)
    ##            pf.Save(None,1)
    ##            task.Run()
    ##        else:
    ##            raise KeyError("%s already exists" % name)
    ##
    ##        task = ts.Activate(name)
    ##        exit_code, startup_error_code = task.GetExitCode()
    ##        return win32api.FormatMessage(startup_error_code)

    ##    Pywin32 comes with a module that lets you do this, win32com.taskscheduler.
    ##    You can use PyITaskScheduler.SetTargetComputer to access tasks on remote
    ##    machines.

except:
    Windows = False

Platform = Windows

# Used in computing file state in converted wallpapers.
def file_checksum(path):
    # Faster RCs possible.
    from md5 import md5
    BUFSIZE = 2 ** 14 # 16384

    read = open(path).read
    hash = md5()
    try:
        while True:
            buf = read(BUFSIZE)
            if buf == '':
                break
            hash.update(buf)

    except EOFError:
        pass

    return hash.hexdigest()
